} \
}
+#ifdef CONFIG_XEN
+inline int skb_checksum_setup(struct sk_buff *skb)
+{
+ if (skb->proto_csum_blank) {
+ if (skb->protocol != htons(ETH_P_IP))
+ goto out;
+ skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl;
+ if (skb->h.raw >= skb->tail)
+ goto out;
+ switch (skb->nh.iph->protocol) {
+ case IPPROTO_TCP:
+ skb->csum = offsetof(struct tcphdr, check);
+ break;
+ case IPPROTO_UDP:
+ skb->csum = offsetof(struct udphdr, check);
+ break;
+ default:
+ if (net_ratelimit())
+ printk(KERN_ERR "Attempting to checksum a non-"
+ "TCP/UDP packet, dropping a protocol"
+ " %d packet", skb->nh.iph->protocol);
+ goto out;
+ }
+ if ((skb->h.raw + skb->csum + 2) > skb->tail)
+ goto out;
+ skb->ip_summed = CHECKSUM_HW;
+ skb->proto_csum_blank = 0;
+ }
+ return 0;
+out:
+ return -EPROTO;
+}
+#else
+inline int skb_checksum_setup(struct sk_buff *skb) {}
+#endif
+
+
/**
* dev_queue_xmit - transmit a buffer
* @skb: buffer to transmit
__skb_linearize(skb, GFP_ATOMIC))
goto out_kfree_skb;
-#ifdef CONFIG_XEN
- /* If a checksum-deferred packet is forwarded to a device that needs a
- * checksum, correct the pointers and force checksumming.
- */
- if (skb->proto_csum_blank) {
- if (skb->protocol != htons(ETH_P_IP))
- goto out_kfree_skb;
- skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl;
- if (skb->h.raw >= skb->tail)
- goto out_kfree_skb;
- switch (skb->nh.iph->protocol) {
- case IPPROTO_TCP:
- skb->csum = offsetof(struct tcphdr, check);
- break;
- case IPPROTO_UDP:
- skb->csum = offsetof(struct udphdr, check);
- break;
- default:
- if (net_ratelimit())
- printk(KERN_ERR "Attempting to checksum a non-"
- "TCP/UDP packet, dropping a protocol"
- " %d packet", skb->nh.iph->protocol);
- rc = -EPROTO;
- goto out_kfree_skb;
- }
- if ((skb->h.raw + skb->csum + 2) > skb->tail)
- goto out_kfree_skb;
- skb->ip_summed = CHECKSUM_HW;
- skb->proto_csum_blank = 0;
- }
-#endif
-
+ /* If a checksum-deferred packet is forwarded to a device that needs a
+ * checksum, correct the pointers and force checksumming.
+ */
+ if(skb_checksum_setup(skb))
+ goto out_kfree_skb;
+
/* If packet is not checksummed and device does not support
* checksumming for this protocol, complete checksumming here.
*/
EXPORT_SYMBOL(net_enable_timestamp);
EXPORT_SYMBOL(net_disable_timestamp);
EXPORT_SYMBOL(dev_get_flags);
+EXPORT_SYMBOL(skb_checksum_setup);
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
EXPORT_SYMBOL(br_handle_frame_hook);
*portptr = newport;
return 1;
}
+diff -r 601fa226a761 net/ipv4/xfrm4_output.c
+--- a/net/ipv4/xfrm4_output.c Wed Apr 19 18:52:30 2006
++++ b/net/ipv4/xfrm4_output.c Thu Apr 20 15:49:40 2006
+@@ -16,6 +16,8 @@
+ #include <net/ip.h>
+ #include <net/xfrm.h>
+ #include <net/icmp.h>
++
++extern int skb_checksum_setup(struct sk_buff *skb);
+
+ /* Add encapsulation header.
+ *
+@@ -103,6 +105,10 @@
+ struct xfrm_state *x = dst->xfrm;
+ int err;
+
++ err = skb_checksum_setup(skb);
++ if (err)
++ goto error_nolock;
++
+ if (skb->ip_summed == CHECKSUM_HW) {
+ err = skb_checksum_help(skb, 0);
+ if (err)